package ;

/**
 * ...
 * @author Mike
 */

import de.polygonal.core.math.interpolation.Interpolation;
import de.polygonal.ds.mem.FloatMemory;
import de.polygonal.ui.UIEvent;
import flash.display3D.Context3D;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.textures.Texture;
import flash.display3D.VertexBuffer3D;
import flash.geom.Matrix3D;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
import flash.Vector;
import de.polygonal.ds.mem.MemoryManager;
import de.polygonal.ds.mem.ByteMemory;
import flash.utils.ByteArray;
import haxe.Log;
import flash.utils.Endian;

class MoleSprite
{
	public var x:Float;
	public var y:Float;
	public var z:Float;
	public var angle:Float;
	public var width:Float;
	public var height:Float;
	public var scaleX:Float;
	public var scaleY:Float;
	public var index: Int;
	public var _context:Context3D;
	public var vertexBuffer:VertexBuffer3D;
	public var _indexBuffer:IndexBuffer3D;
	public var _matrix:Matrix3D;
	public var poly : Int;
	public var hasDirtyVectorBuffer : Bool;
	public var hasDirtyIndexBuffer : Bool;

	//static var a: flash.Vector<Float> = new flash.Vector<Float>();
	//static var a: ByteMemory = new ByteMemory( 100000 );
	static var a: ByteArray = null;

	static var i: flash.Vector<UInt> = new flash.Vector<UInt>();
	static var data32PerVertex : Int = 4;
	private static var QUAD : Int = 4;
	
	static var total : Int;
	
/*	public function newGrid(context:Context3D)
	{
		this._context    = context;
		Log.trace( "TOT:" + total );
		this.vertexBuffer     =  this._context.createVertexBuffer( total * QUAD,  data32PerVertex ); //x, y, z, u, v
		
		a.endian = Endian.LITTLE_ENDIAN;
		this._indexBuffer = this._context.createIndexBuffer( total * 6 ); 
		
		_matrix     = new Matrix3D();
		x           = -0;
		y           = -0;
		z           = 10;
		width       = 0;
		height      = 0;
		angle    	= 60;
		scaleX      = 2;
		scaleY      = 2;
		index = 0;
		var poly:Int  = 0;
		var dy = 0;
		var dx = 0;
		var size : Float = 1;
		var totladiv2 : Int = Std.int( total/2 );
		
		var tx = (1 / 1024) * 8;
		var rnd : Int = 0;
		
		for ( dy in 0...120 ) {
			var tdy = dy * tx;
			for ( dx in 0...120 ) {
				
				var tdx = dx * tx;
				rnd = Std.int( Math.random() * 60 );
				
				pushMatrix( 0, 0, rnd );
				pushVertex( Std.int((dx-60) - size/2), Std.int((dy-60) + size/2) );
				pushUV( tdx, tdy + tx );
				
				pushMatrix( 0, 0, rnd );
				pushVertex( Std.int((dx-60) - size/2), Std.int((dy-60) - size/2) );
				pushUV( tdx, tdy );
				
				pushMatrix( 0, 0, rnd );
				pushVertex( Std.int((dx-60) + size/2), Std.int((dy-60) - size/2) );
				pushUV( tdx+tx, tdy );

				pushMatrix( 0,0, rnd );
				pushVertex( Std.int((dx-60) + size/2), Std.int((dy-60) + size/2) );
				pushUV( tdx + tx, tdy + tx );
				
				i.push( poly + 0 );
				i.push( poly + 1 );
				i.push( poly + 2 );
				i.push( poly + 0 );
				i.push( poly + 2 );
				i.push( poly + 3 );
				poly += 4;
				
			}
			
		}
		/*CCW ordering; first point is NW; uv coordinates upside-down
		sendVectorToGPU();
		_indexBuffer.uploadFromVector( i , 0, total * 6 );


	}
	*/
	public inline function sendIndexToGPU() {
		
		if ( this.hasDirtyIndexBuffer )
		{
			this._indexBuffer = this._context.createIndexBuffer( total*6 ); //x, y, z, u, v
		}
		_indexBuffer.uploadFromVector(  i , 0, total*6 );

	}
	
	public inline function sendVectorToGPU() {
		
		if ( this.hasDirtyVectorBuffer )
		{
			this.vertexBuffer = this._context.createVertexBuffer( total*4, data32PerVertex ); //x, y, z, u, v
		}
		Log.trace( "Total" + a.bytesAvailable + "    Len    ->" + Std.int(a.length/4) );
		vertexBuffer.uploadFromByteArray(  a , 0 , 0, 8 );
	}
	public function new(context:Context3D)
	{
		
		this._context     = context;
		a = new ByteArray();
		a.endian = Endian.LITTLE_ENDIAN;
		a.length = 128*4;
		
		_matrix = new Matrix3D();
		x       = -0;
		y       = -0;
		z       = 0;
		width   = 0;
		height  = 0;
		angle   = 0;
		scaleX  = 1;
		scaleY  = 1;
		poly 	= 0;
		total 	= 0;
		
		addQuad( 255, 255, 0,  100, 100, 10, 1, 1);
		addQuad( 255, 255, 0, 100, 100, 10, 1, 1);

		sendVectorToGPU();
		sendIndexToGPU();
		
	}
	
	public function getVertexBuffer() : VertexBuffer3D { return this.vertexBuffer; }
	public function getIndexBuffer() : IndexBuffer3D { return this._indexBuffer; }
	
	public function draw( shader )
	{
		this._context.drawTriangles( _indexBuffer );
	}
	
	public function addQuad( x, y, z, width, height, rotation, scaleX, scaleY ) : Void
	{
		//CCW ordering; first point is NW; uv coordinates upside-down
		
		/*      0 ------- 1
				|         |
				|         |
				|         |
				3---------2
		*/
				
		var halfWidth : Float = width / 2;
		var halfHeight : Float = height / 2;
		
		for ( i in 5...8 ){
			pushVertex( x, y, z );
			//pushVertex( Std.int(-halfWidth), Std.int(-halfHeight) );
			pushUV( 0, 0,0 ); //0,0
		}		

		poly = total << 2;
		
		i.push( poly + 0 );	i.push( poly + 1 );	i.push( poly + 2 );	
		i.push( poly + 0 ); i.push( poly + 2 ); i.push( poly + 3 );

		total++;
		this.hasDirtyVectorBuffer = true;
		this.hasDirtyIndexBuffer = true;
	}

	inline function pushVertex(x : Float , y : Float, z : Float ) : Void {
		a.writeFloat( x );
		a.writeFloat( y );
		a.writeFloat( z );	
	}	
	
	inline function pushUV( id : Int, u : Float, v : Float) : Void {
		a.writeByte( 0 );
		a.writeByte( 0 );
		a.writeByte( 0 );
		a.writeByte( 0 );
	}		
	
	public function getWorldTransform():Matrix3D
	{
		_matrix.identity();
		_matrix.appendRotation( angle, Vector3D.Z_AXIS );
		_matrix.appendScale( (scaleX), (scaleY), 1 );
		_matrix.appendTranslation( x, y, z );
		return _matrix;
	}	
}